﻿using RayDen.Library.Components.Color.Types;
using RayDen.Library.Core;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine;
using RayDen.RayEngine.Core.Types;
using RayEngine.Spectral.Entities.Materials;

namespace RayEngine.Spectral.Entities.Lighting
{
    public class PointLight : BaseLight
    {
        protected IColorType power;
        protected Point Position;

        public PointLight(LightMaterial mt, Point pt)
            : base(mt)
        {
            float pdf;
            this.Position = pt;
            this.power = mt.GetEmittance(0f, 0f, out pdf);
        }

        public override bool IsDelta()
        {
            return true;
        }

        public override IColorType Emit(ref Vector dir, out float pdf)
        {
            //pdf = MathLab.INV4PI;
            pdf = 1f;
            return power.CloneValue().Mul(1f / (Position - dir).Length2());
        }

        public override void EvaluateShadow(ShadePointInfo pt, float u0, float u1, float u2, out IColorType radiance, out float pdf, out RayData ray)
        {
            var dir = -(Position - pt.HitPoint);
            var l2 = dir.Length2();
            var l = MathLab.Sqrt(l2);
            dir.Normalize();
            pdf = MC.UniformSpherePdf();
            ray = new RayData(ref pt.HitPoint, ref dir, 1e-4f, l - 1e-4f);
            radiance = power.Mul(1f / l);
            //float theta = Vector.SphericalTheta(ref dir);
            //Profile.Evaluate(Vector.SphericalPhi(ref dir) * MathLab.INVTWOPI, theta * MathLab.INVPI);
        }

        public override void EvaluateIllumination(RayEngineScene scn, float u0, float u1, float u2, float u3, float u4, out RayData ray, out float pdf, out IColorType radiance)
        {
            Vector dir = MC.UniformSampleSphere(u0, u1);

            ray = new RayData(ref Position, ref dir, 1e-4f, 1e4f);

            pdf = MathLab.INV4PI;

            radiance = (power.Mul(MathLab.M_PI * 4f));
        }
    }
}